﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Kooboo.Commerce.Contexts.Categories;
using Kooboo.Commerce.Contexts.ProductTypes;
using Kooboo.IoC;
using Kooboo.Web.Mvc;
using Kooboo.Web.Mvc.Paging;

namespace Kooboo.Web.Areas.Commerce.Controllers
{
    using Kooboo.Commerce;

    [Authorize(Roles = "Administrator")]
    public class CategoryController : ManagementController
    {
        public ActionResult Index()
        {
            var root = this.Actor.QueryCategories().Where(i => i.Parent == null);

            var list = new List<ICategory>();

            foreach (var i in root)
            {
                list.AddRange(BuildItem(i));
            }

            ViewData["change-parent-action"] = this.Url.Action<CategoryController>(i => i.ChangeParent(null, null));

            return View(list);
        }

        public ActionResult Products(int id, int? page, int? pagesize)
        {

            var category = this.Actor.QueryCategories().FirstOrDefault(i => i.Id == id);
            ViewData["Category"] = category;

            ViewData["ProductTypes"] = this.Actor.QueryProductTypes().Where(i => i.IsEnable).AsEnumerable();

            if (category != null)
            {
                var list = category.Products
                    .OrderByDescending(i => i.Id)
                    .Select(i => new ProductModel
                    {
                        Id = i.Id,
                        //  SKU = i.SKU,
                        Name = i.Name,
                        //  PurchasePrice = i.PurchasePrice,
                        //  RetailPrice = i.RetailPrice,
                        BrandName = i.Brand.Name,
                        ProductTypeName = i.ProductType.Name,
                        //  Stock = i.Stock,
                        //  Hidden = i.Hidden,
                        //  CanBackOrder = i.CanBackOrder
                    });

                return View(list.ToPagedList(page ?? 1, pagesize ?? Configuration.PageSize));
            }

            return View(new List<ProductModel>().ToPagedList(page ?? 1, pagesize ?? Configuration.PageSize));
        }

        List<ICategory> BuildItem(ICategory category)
        {
            var list = new List<ICategory>();

            list.Add(category);

            foreach (var i in category.Children)
            {
                list.AddRange(BuildItem(i));
            }

            return list;
        }

        #region Create

        public ActionResult Create(int? parentId)
        {
            var category = ObjectContainer.CreateInstance<ICategory>();
            if (parentId.HasValue)
            {
                var parent = ObjectContainer.CreateInstance<ICategory>();
                parent.Id = parentId.Value;
                category.Parent = parent;
            }

            var allCategories = this.Actor.QueryCategories().Where(c => c.Parent == null);
            ViewData["BindingCategories"] = CreateBindingCategories(allCategories, parentId.HasValue ? new ICategory[] { category.Parent } : null);
            ViewData["CategoryContainerID"] = "Parent.ID";

            ViewData["UploadUrl"] = this.Url.Action<ImageController>(i => i.Upload("category", false));
            ViewData["PhotoUrl"] = category.BuildThubmailPhotoUrl();

            return View(category);
        }

        [HttpPost]
        public ActionResult Create(ICategory category)
        {

            this.SetNullParent(category);

            if (this.ModelState.IsValid)
            {
                try
                {

                    this.Actor.Post(category);

                    ViewData["Message"] = "Add category successfully";

                    return RedirectToIndex();
                }
                catch (Exception ex)
                {
                    ViewData["ErrorMessage"] = ex.Message;
                }
            }

            return View(category);
        }

        private void SetNullParent(ICategory category)
        {
            var parent = this.ModelState["Parent.Id"];
            if (parent != null && parent.Errors.Count > 0)
            {
                this.ModelState.Remove("Parent.Id");
                category.Parent = null;
            }
        }

        #endregion

        #region Edit

        public ActionResult Edit(int id)
        {
            var allCategories = this.Actor.QueryCategories().Where(c => c.Parent == null);
            var category = this.Actor.QueryCategories().FirstOrDefault(i => i.Id == id); //current Category

            if (category == null)
                return View("NotFound");

            ViewData["BindingCategories"] = CreateBindingCategories(allCategories, category.Parent != null ? new ICategory[] { category.Parent } : null, category);
            ViewData["CategoryContainerID"] = "Parent.ID";

            ViewData["UploadUrl"] = this.Url.Action<ImageController>(i => i.Upload("category", false));
            ViewData["PhotoUrl"] = category.BuildThubmailPhotoUrl();

            return View(category);
        }

        [HttpPost]
        public ActionResult Edit(ICategory category)
        {
            this.SetNullParent(category);

            if (ModelState.IsValid)
            {
                try
                {

                    this.Actor.Put(category);
                    ViewData["Message"] = "Update category successfully";

                    return RedirectToIndex();
                }
                catch (Exception ex)
                {
                    ViewData["ErrorMessage"] = ex.Message;
                }
            }

            return View(category);
        }

        #endregion

        #region Delete

        [HttpPost]
        public ActionResult Delete(ICategory category)
        {
            try
            {
                this.Actor.Delete(category);
                ViewData["Message"] = "Delete category successfully";
            }
            catch (Exception ex)
            {
                ViewData["ErrorMessage"] = ex.Message;
            }

            return RedirectToIndex();
        }

        #endregion

        #region ChangeParent

        [HttpPost]
        public ActionResult ChangeParent(ICategory category, int? parentId)
        {

            try
            {
                if (parentId.HasValue)
                {
                    var parent = ObjectContainer.CreateInstance<ICategory>();
                    parent.Id = parentId.Value;
                    category.MoveTo(parent);
                }
                else
                {
                    category.MoveTo(null);
                }

                ViewData["Message"] = "Move category successfully";
            }
            catch (Exception ex)
            {
                ViewData["ErrorMessage"] = ex.Message;
            }

            return RedirectToIndex();
        }

        #endregion

        /// <summary>
        /// combian categories and selected categories to a new object
        /// </summary>
        /// <param name="allCategories"></param>
        /// <param name="selectedCategories"></param>
        /// <returns></returns>
        private IEnumerable<BindingCategory> CreateBindingCategories(IEnumerable<ICategory> categories,
            IEnumerable<ICategory> selectedCategories, ICategory removeCategory = null)
        {
            if (categories != null && categories.Count() > 0)
            {
                if (removeCategory != null)
                {
                    categories = categories.Where(c => c.Id != removeCategory.Id);
                }

                if (selectedCategories == null || selectedCategories.Count() == 0)
                {
                    return categories
                        .Select(c =>
                        new BindingCategory()
                        {
                            ID = c.Id,
                            Name = c.Name,
                            Selected = "",
                            Children = CreateBindingCategories(c.Children, selectedCategories, removeCategory)
                        });
                }
                else
                {
                    return categories.Select(c =>
                           new BindingCategory()
                           {
                               ID = c.Id,
                               Name = c.Name,
                               Selected = (selectedCategories.Where(sc => sc.Id == c.Id).Count() > 0 ? "checked" : ""),
                               Children = CreateBindingCategories(c.Children, selectedCategories, removeCategory)
                           });
                }
            }
            else
            {
                return Enumerable.Empty<BindingCategory>();
            }
        }
    }
}
